package com.examination.client.service.impl;

import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.examination.client.config.ConfigProperties;
import com.examination.client.domian.dto.*;
import com.examination.client.domian.vo.QueryUserListVO;
import com.examination.client.entity.CourierSite;
import com.examination.client.entity.UserInfo;
import com.examination.client.enums.BusinessExceptionEnum;
import com.examination.client.enums.DeleteStatusEnum;
import com.examination.client.exception.BusinessException;
import com.examination.client.mapper.UserInfoMapper;
import com.examination.client.mapper.UserMenuMapper;
import com.examination.client.redis.RedisCache;
import com.examination.client.service.ICourierSiteService;
import com.examination.client.service.IUserInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.examination.client.service.IUserMenuService;
import com.examination.client.util.*;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.apache.http.util.TextUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author xiaodong
 * @since 2021-10-20
 */
@Slf4j
@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements IUserInfoService {

    @Resource
    ConfigProperties configProperties;

    @Resource
    private ICourierSiteService courierSiteService;

    @Resource
    private UserMenuMapper userMenuMapper;

    @Resource
    private IUserMenuService userMenuService;


    @Autowired
    private RedisCache redisCache;

    @Override
    public Boolean save(UserInfoDTO userInfoDTO)throws Exception {

        UserInfo userInfo = findByUsername(userInfoDTO.getUserName(), userInfoDTO.getUserType());
        if(Objects.nonNull(userInfo)){
            throw new BusinessException(BusinessExceptionEnum.REPEAT.code,BusinessExceptionEnum.REPEAT.msg);
        }
        userInfo = new UserInfo();
        BeanUtils.copyProperties(userInfoDTO,userInfo);
        userInfo.setCreateTime(new Date());
        if(2==userInfoDTO.getUserType()){
            userInfo.setSiteId(UserInfoUtil.getSiteId());
            boolean success = save(userInfo);
            UserInfo userInfo1 = findByUsername(userInfo.getUserName(), 2);
            log.info("userInfo1 ------- > ");
            log.info(JsonUtils.toJson(userInfo1));
            return userMenuService.save(userInfo1, userInfoDTO.getMenuList());
        }
        if(1==userInfoDTO.getUserType()){
            synchronizeUser(userInfoDTO.getUserName(),"1");
            return save(userInfo);
        }
        return false;
    }


    /**
     * 同步数据
     * @param phone
     * @param psstatus
     * @throws Exception
     */
    private void synchronizeUser(String phone,String  psstatus) throws Exception {
        try {
            HashMap<String, String> header = new HashMap<>();
            Map<String, String> map = new HashMap<>();
            map.put("phone",phone);
            map.put("psstatus",psstatus);
            HttpResponse httpResponse = HttpUtils.doGet(configProperties.getUrl(), "/ShenBian_Web/setExpressRelation.do", null, header, map);
            HttpEntity entity = httpResponse.getEntity();
            if(entity!=null){
                String result = EntityUtils.toString(entity,"UTF-8");
                JSONObject jsonObject = JSONObject.parseObject(result);
                if(!"200".equals(jsonObject.get("code"))){
                    log.info("同步数据失败:{}",jsonObject.get("info"));
                }
            }
        } catch (Exception e) {
            throw new BusinessException("同步到身边后台用户数据失败");
        }
    }


    @Override
    public Boolean modify(UserInfoDTO userInfoDTO)throws Exception {
        log.info("用户修改:{}", JsonUtils.toJson(userInfoDTO));
        UserInfo userInfo = findByUsername(userInfoDTO.getUserName(), userInfoDTO.getUserType());
        if(Objects.nonNull(userInfo) && !userInfo.getUserId().equals(userInfoDTO.getUserId())){
            throw new BusinessException(BusinessExceptionEnum.REPEAT.code,BusinessExceptionEnum.REPEAT.msg);

        }
        userInfo = new UserInfo();
        BeanUtils.copyProperties(userInfoDTO,userInfo);
        userInfo.setUpdateTime(new Date());
        if (userInfoDTO.getUserType() == 2) {
            userMenuService.modify(userInfoDTO);
        }
        return updateById(userInfo);
    }

    @Override
    public Boolean modifyAppSite(UserInfoDTO userInfoDTO) throws Exception {
        log.info("用户可操做子站点修改:{}", JsonUtils.toJson(userInfoDTO));
        UserInfo userInfo = findByUserId(userInfoDTO.getUserId());
        userInfo.setUpdateTime(new Date());
        String appSite = null;
        if (userInfoDTO.getAppSiteList() != null) {
            for (int i = 0; i < userInfoDTO.getAppSiteList().size(); i ++) {
                if (i == 0) {
                    appSite = userInfoDTO.getAppSiteList().get(i);
                } else {
                    appSite += "," + userInfoDTO.getAppSiteList().get(i);
                }
            }
        }
        userInfo.setAppSite(appSite);
        return updateById(userInfo);
    }

    @Override
    public UserInfo findByUsername(String userName,Integer platformType) {

        LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(UserInfo::getUserName,userName);
        queryWrapper.eq(UserInfo::getUserType,platformType);
        queryWrapper.eq(UserInfo::getDeleteStatus, DeleteStatusEnum.NOT_DELETED.getCode());
        return getOne(queryWrapper);


    }
    @Override
    public UserInfo findByUsernameToPassword(String userName,String password) {
        LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(UserInfo::getUserName,userName);
        queryWrapper.eq(UserInfo::getPassword,password);
        queryWrapper.eq(UserInfo::getDeleteStatus, DeleteStatusEnum.NOT_DELETED.getCode());
        return getOne(queryWrapper);
    }

    @Override
    public UserInfo findByUserId(Integer userId) {
        LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(UserInfo::getUserId,userId);
        queryWrapper.eq(UserInfo::getDeleteStatus, DeleteStatusEnum.NOT_DELETED.getCode());
        return getOne(queryWrapper);
    }

    @Override
    public Page<QueryUserListVO> systemList(QueryUserDTO queryUserDTO) {
        Page<UserInfo> page = new Page<>();
        page.setSize(queryUserDTO.getSize());
        page.setCurrent(queryUserDTO.getCurrent());
        LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(queryUserDTO.getUserName()),UserInfo::getUserName,queryUserDTO.getUserName())
                     .eq(StringUtils.isNotBlank(queryUserDTO.getUserPhone()),UserInfo::getUserPhone,queryUserDTO.getUserPhone())
                     .eq(Objects.nonNull(queryUserDTO.getSiteId()),UserInfo::getSiteId,queryUserDTO.getSiteId())
                     .eq(UserInfo::getUserType,2)
                     .eq(UserInfo::getDeleteStatus,DeleteStatusEnum.NOT_DELETED.getCode());
        Page pageList = page(page, queryWrapper);

        List<UserInfo> records = pageList.getRecords();
        List<QueryUserListVO> queryUserListVOList = Lists.newArrayList();
        if(!CollectionUtils.isEmpty(records)){
            records.forEach(e->{
                QueryUserListVO queryUserListVO = new QueryUserListVO();
                BeanUtils.copyProperties(e,queryUserListVO);
                CourierSite courierSite = courierSiteService.getById(e.getSiteId());
                queryUserListVO.setSiteName(courierSite.getSiteName());
                queryUserListVOList.add(queryUserListVO);

            });
        }
        return pageList.setRecords(queryUserListVOList);
    }

    @Override
    public Boolean deleteUser(String userId) throws Exception{
        UserInfo userInfo = getById(userId);
        if(Objects.nonNull(userInfo)){
            synchronizeUser(userInfo.getUserName(),"0");

        }


        return  removeById(userId);
    }

    @Override
    public AccountDTO info(String phone) throws BusinessException {

        UserInfo userInfo = findByUsername(phone,1);

        if(Objects.isNull(userInfo)){
            throw new BusinessException(BusinessExceptionEnum.USER_INVALID.code,BusinessExceptionEnum.USER_INVALID.msg);
        }
        CourierSite courierSite = courierSiteService.getById(userInfo.getSiteId());
        UserTokenDTO userTokenDTO = new UserTokenDTO();
        BeanUtils.copyProperties(userInfo,userTokenDTO);
        userTokenDTO.setParentSiteId(courierSite.getParentId());

        String token = JwtTokenUtil.createToken(userTokenDTO);

        AccountDTO accountDTO = new AccountDTO();
        accountDTO.setUserName(userInfo.getUserName());
        accountDTO.setSiteName(courierSite.getSiteName());
        accountDTO.setToken(token);
        accountDTO.setSiteId(courierSite.getId());
        return accountDTO;
    }

    @Override
    public Page<QueryUserListVO> appList(QueryUserDTO queryUserDTO) {
        Page<UserInfo> page = new Page<>();
        page.setSize(queryUserDTO.getSize());
        page.setCurrent(queryUserDTO.getCurrent());
        LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(queryUserDTO.getUserName()),UserInfo::getUserName,queryUserDTO.getUserName())
                .eq(StringUtils.isNotBlank(queryUserDTO.getUserPhone()),UserInfo::getUserPhone,queryUserDTO.getUserPhone())
                .eq(Objects.nonNull(queryUserDTO.getSiteId()),UserInfo::getSiteId,queryUserDTO.getSiteId())
                .eq(UserInfo::getUserType,1)
                .eq(UserInfo::getDeleteStatus,DeleteStatusEnum.NOT_DELETED.getCode());
        Page pageList = page(page, queryWrapper);
        List<UserInfo> records = pageList.getRecords();
        List<QueryUserListVO> queryUserListVOList = Lists.newArrayList();
        if(!CollectionUtils.isEmpty(records)){
            records.forEach(e->{
                QueryUserListVO queryUserListVO = new QueryUserListVO();
                BeanUtils.copyProperties(e,queryUserListVO);
                CourierSite courierSite = courierSiteService.getById(e.getSiteId());
                if (courierSite != null && courierSite.getParentId() == 0) {
                    queryUserListVO.setIsParentSite(0);
                } else {
                    queryUserListVO.setIsParentSite(1);
                }
                queryUserListVO.setSiteName(Objects.nonNull(courierSite)? courierSite.getSiteName():"");
                /**
                 * 可操作的子站点账号
                 */
                List<String> appSiteList = new ArrayList<>();
                if (!TextUtils.isEmpty(e.getAppSite())) {
                    if (e.getAppSite().contains(",")) {
                        appSiteList = Arrays.asList(e.getAppSite().split(","));
                    } else {
                        appSiteList.add(e.getAppSite());
                    }
                }
                queryUserListVO.setAppSiteList(appSiteList);
                queryUserListVOList.add(queryUserListVO);

            });
        }
        return pageList.setRecords(queryUserListVOList);
    }

    /**
     * 查询该用户的所有菜单信息
     */
    @Override
    @Transactional
    public List<MenuSearchDTO> listMenu(Integer userId, Integer select_status) {
        MenuSearchDTO menuSearchDTO = new MenuSearchDTO();
        menuSearchDTO.setUserId(userId);
        menuSearchDTO.setSelectStatus(select_status);
        return userMenuMapper.selectMenuByUser(menuSearchDTO);
    }

    @Override
    public String register(RegistersUser registersUser){
        String msg = "", phone = registersUser.getUserPhone(),
                code = registersUser.getCode(),
                password = registersUser.getPassword(),
                passwordVerify = registersUser.getPasswordVerify();
        LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserInfo::getUserPhone,phone);
        queryWrapper.eq(UserInfo::getUserType,1);
        queryWrapper.eq(UserInfo::getDeleteStatus, DeleteStatusEnum.NOT_DELETED.getCode());
        Object cacheObject = redisCache.getCacheObject(phone);
        List<UserInfo> list = list(queryWrapper);
        if (list != null && list.size() > 0){
            msg = "当前手机号已注册！";
        }else if (cacheObject == null || !code.equals(Convert.toStr(cacheObject))){
            msg = "验证码不正确！";
        }else if(!password.equals(passwordVerify)){
            msg = "两次输入密码不一样！";
        }else{
            UserInfo userInfo  = new UserInfo();
            userInfo.setUserName(registersUser.getUserName());
            userInfo.setPassword(registersUser.getPassword());
            userInfo.setUserName(registersUser.getUserName());
            userInfo.setCreateTime(new Date());
            boolean save = save(userInfo);
            if (save){
                ThreadLocalUtils.removeByKey(phone);
                msg = "注册成功！";
            }else{
                msg = "注册失败！";
            }
        }
        return msg;
    }

}
